Load the libraries

Create the curated dataset

Log transform what is needed and select the needed columns

## Parsed with column specification:
## cols(
##   Species = col_character(),
##   New_Species = col_character(),
##   Class = col_character(),
##   Order = col_character(),
##   Family = col_character(),
##   Max_Longevity = col_double(),
##   Log_Longevity = col_double(),
##   Clutch_Litter_size = col_double(),
##   Mean_age_at_breeding = col_double(),
##   Maximum_Broods_per_year = col_double(),
##   Log_Hatchling_Mass = col_double(),
##   Origin_Of_Data = col_character(),
##   Log_Female_Mass = col_double()
## )
## # A tibble: 6 x 7
##   Class Log_Female_Mass log_longevity log_clutch log_breading_age log_brood
##   <chr>           <dbl>         <dbl>      <dbl>            <dbl>     <dbl>
## 1 Amph…         0.544           0.477       2.78          -0.745      0    
## 2 Amph…        -0.0438          0.322       2.80          -0.523      0    
## 3 Amph…         2.05            1.08        2.91          -0.301      0    
## 4 Amph…         0.00303         0.477       1.29          -0.125      0    
## 5 Amph…         1.61            0.322       2.86          -0.0969     0    
## 6 Amph…         0.595           0.614       2.43           0          0.301
## # … with 1 more variable: Log_Hatchling_Mass <dbl>

Running the FA model and extracting the factors for 1,2, and 3 factors. And running the MFA model Storing everything in a nested dataset

#create a nested dataset with all the tetrapods
all_tetra_nest<- tetrapod_data %>% 
  dplyr::select(-Class) %>% 
  nest() %>%
  add_column(Class = "Tetrapods",.before = 1)

#create a nested dataset by class, add the whole tetrapods and map the models into them
tetrapod_nested<- tetrapod_data %>%
  nest(-Class) %>%
  bind_rows(all_tetra_nest) %>% 
  mutate(model.fa1 = map(data, function(df) factanal(df,1,rotation="varimax",scores = "regression"))) %>% 
  mutate(model.fa2 = map(data, function(df) factanal(df,2,rotation="varimax",scores = "regression"))) %>% 
  mutate(model.fa3 = map(data, function(df) factanal(df,3,rotation="varimax",scores = "regression"))) %>%
  mutate(model.mfa = map(data, function (df) MFA(df,group = c(1,1,1,1,1,1), type=c(rep("s",1),rep("s",1),rep("s",1),rep("s",1),rep("s",1),rep("s",1)),name.group = c("Body Size","Longevity","Clutch size","Age at breeding","Brood freq","Hatchling mass"),
                                                 ncp = 5,graph = F))) %>% 
  group_by(Class) %>% 
  mutate(model.fa1.r = map(model.fa1, function(model) broom::tidy(model)), 
         model.fa2.r = map(model.fa2, function(model) broom::tidy(model)),
         model.fa3.r = map(model.fa3, function(model) broom::tidy(model))) %>% 
  mutate(model.fa1.r = map(model.fa1.r, function (df) mutate(df, com.var = 1 - uniqueness)),
         model.fa2.r = map(model.fa2.r, function (df) mutate(df, com.var = 1 - uniqueness)),
         model.fa3.r = map(model.fa3.r, function (df) mutate(df, com.var = 1 - uniqueness))) %>% 
  mutate(mfa.coord = map(model.mfa,function(mfa) mfa$quanti.var$coord[,1:3]))

# check the data
tetrapod_nested
## # A tibble: 5 x 10
## # Groups:   Class [5]
##   Class data  model.fa1 model.fa2 model.fa3 model.mfa model.fa1.r
##   <chr> <lis> <list>    <list>    <list>    <list>    <list>     
## 1 Amph… <tib… <factana… <factana… <factana… <MFA>     <tibble [6…
## 2 Aves  <tib… <factana… <factana… <factana… <MFA>     <tibble [6…
## 3 Mamm… <tib… <factana… <factana… <factana… <MFA>     <tibble [6…
## 4 Rept… <tib… <factana… <factana… <factana… <MFA>     <tibble [6…
## 5 Tetr… <tib… <factana… <factana… <factana… <MFA>     <tibble [6…
## # … with 3 more variables: model.fa2.r <list>, model.fa3.r <list>,
## #   mfa.coord <list>

Mammals

Factor Analysis with factanal function

Exploratory power

We can see that in all the factors it’s quite strong exploratory power. We can use the parallel analysis to see how many factors we should use. You see that by looking at where the blue line (the actual data) breaks and where the difference between the blue line and the red line (simulated data) is the smallest. Based on this three might be more sutible but it has 0 degrees of freedom so we will take Two Factors.

## Parallel analysis suggests that the number of factors =  3  and the number of components =  NA

The results for Three factors

The common variance (column com.var) shows how much of the variance is shared between a specific variable and the rest of the variables. The larger the number the more informative the variable.

## [[1]]
## # A tibble: 6 x 5
##   variable           uniqueness    fl1    fl2 com.var
##   <chr>                   <dbl>  <dbl>  <dbl>   <dbl>
## 1 Log_Female_Mass         0.202  0.471  0.759   0.798
## 2 log_longevity           0.226  0.746  0.465   0.774
## 3 log_clutch              0.559 -0.520 -0.413   0.441
## 4 log_breading_age        0.106  0.872  0.367   0.894
## 5 log_brood               0.307 -0.778 -0.295   0.693
## 6 Log_Hatchling_Mass      0.005  0.349  0.934   0.995
variable uniqueness fl1 fl2 com.var
Log_Female_Mass 0.2024090 0.4709061 0.7588400 0.7975910
log_longevity 0.2263958 0.7463529 0.4653622 0.7736042
log_clutch 0.5592237 -0.5195702 -0.4133064 0.4407763
log_breading_age 0.1055722 0.8717895 0.3666210 0.8944278
log_brood 0.3071465 -0.7781869 -0.2954299 0.6928535
Log_Hatchling_Mass 0.0050000 0.3493945 0.9343044 0.9950000

Birds

Factor Analysis with factanal function

Exploratory power

We can see that in all the factors it’s quite strong exploratory power. We can use the parallel analysis to see how many factors we should use. In our case it’s Two Factors

## Parallel analysis suggests that the number of factors =  2  and the number of components =  NA

The results for Two factors

The common variance (column com.var) shows how much of the variance is shared between a specific variable and the rest of the variables. The larger the number the more informative the variable.

## [[1]]
## # A tibble: 6 x 5
##   variable           uniqueness    fl1    fl2 com.var
##   <chr>                   <dbl>  <dbl>  <dbl>   <dbl>
## 1 Log_Female_Mass       0.00812  0.986  0.141   0.992
## 2 log_longevity         0.514    0.575  0.395   0.486
## 3 log_clutch            0.420   -0.125 -0.751   0.580
## 4 log_breading_age      0.160    0.542  0.739   0.840
## 5 log_brood             0.756   -0.420 -0.260   0.244
## 6 Log_Hatchling_Mass    0.0731   0.916  0.296   0.927
variable uniqueness fl1 fl2 com.var
Log_Female_Mass 0.0081211 0.9858722 0.1411915 0.9918789
log_longevity 0.5138691 0.5747281 0.3947403 0.4861309
log_clutch 0.4198854 -0.1252311 -0.7512836 0.5801146
log_breading_age 0.1601473 0.5417116 0.7391895 0.8398527
log_brood 0.7561382 -0.4199588 -0.2598803 0.2438618
Log_Hatchling_Mass 0.0731074 0.9160586 0.2961911 0.9268926

Reptiles

Factor Analysis with factanal function

Exploratory power

We can see that in all the factors it’s quite strong exploratory power. We can use the parallel analysis to see how many factors we should use. In our case it’s Two Factors

## Parallel analysis suggests that the number of factors =  4  and the number of components =  NA

The results for Two factors

The common variance (column com.var) shows how much of the variance is shared between a specific variable and the rest of the variables. The larger the number the more informative the variable.

## [[1]]
## # A tibble: 6 x 5
##   variable           uniqueness    fl1    fl2 com.var
##   <chr>                   <dbl>  <dbl>  <dbl>   <dbl>
## 1 Log_Female_Mass         0.005  0.531  0.844  0.995 
## 2 log_longevity           0.108  0.908  0.259  0.892 
## 3 log_clutch              0.532  0.187  0.658  0.468 
## 4 log_breading_age        0.274  0.762  0.380  0.726 
## 5 log_brood               0.961 -0.156 -0.122  0.0392
## 6 Log_Hatchling_Mass      0.172  0.628  0.658  0.828
variable uniqueness fl1 fl2 com.var
Log_Female_Mass 0.0050000 0.5311291 0.8443390 0.9950000
log_longevity 0.1082916 0.9080053 0.2592963 0.8917084
log_clutch 0.5323162 0.1871770 0.6577486 0.4676838
log_breading_age 0.2744691 0.7623471 0.3799387 0.7255309
log_brood 0.9607840 -0.1558700 -0.1219647 0.0392160
Log_Hatchling_Mass 0.1722643 0.6283427 0.6579677 0.8277357

Amphibians

Factor Analysis with factanal function

Exploratory power

We can see that in all the factors it’s quite strong exploratory power. We can use the parallel analysis to see how many factors we should use. In our case it’s Two Factors

## Parallel analysis suggests that the number of factors =  2  and the number of components =  NA

The results for Two factors

The common variance (column com.var) shows how much of the variance is shared between a specific variable and the rest of the variables. The larger the number the more informative the variable.

In here you see that some of the variables don’t add much to the model (com.var is low)

## [[1]]
## # A tibble: 6 x 5
##   variable           uniqueness     fl1     fl2 com.var
##   <chr>                   <dbl>   <dbl>   <dbl>   <dbl>
## 1 Log_Female_Mass         0.712  0.509   0.170    0.288
## 2 log_longevity           0.214  0.884   0.0708   0.786
## 3 log_clutch              0.005 -0.125   0.990    0.995
## 4 log_breading_age        0.605  0.615  -0.128    0.395
## 5 log_brood               0.883 -0.342  -0.0145   0.117
## 6 Log_Hatchling_Mass      0.871 -0.0843 -0.350    0.129
variable uniqueness fl1 fl2 com.var
Log_Female_Mass 0.7116636 0.5094013 0.1698506 0.2883364
log_longevity 0.2139989 0.8837348 0.0707921 0.7860011
log_clutch 0.0050000 -0.1248152 0.9896571 0.9950000
log_breading_age 0.6051064 0.6152799 -0.1276403 0.3948936
log_brood 0.8830899 -0.3416131 -0.0145175 0.1169101
Log_Hatchling_Mass 0.8705508 -0.0842664 -0.3497850 0.1294492

All tetrapods

Factor Analysis with factanal function

Exploratory power

We can see that in all the factors it’s quite strong exploratory power. We can use the parallel analysis to see how many factors we should use. In our case it’s Two Factors

## Parallel analysis suggests that the number of factors =  3  and the number of components =  NA

The results for Two factors

The common variance (column com.var) shows how much of the variance is shared between a specific variable and the rest of the variables. The larger the number the more informative the variable.

## [[1]]
## # A tibble: 6 x 5
##   variable           uniqueness     fl1      fl2 com.var
##   <chr>                   <dbl>   <dbl>    <dbl>   <dbl>
## 1 Log_Female_Mass         0.181  0.520   0.741     0.819
## 2 log_longevity           0.321  0.779   0.269     0.679
## 3 log_clutch              0.777  0.0127 -0.472     0.223
## 4 log_breading_age        0.222  0.882   0.00332   0.778
## 5 log_brood               0.718 -0.459  -0.267     0.282
## 6 Log_Hatchling_Mass      0.005  0.432   0.899     0.995
variable uniqueness fl1 fl2 com.var
Log_Female_Mass 0.1810837 0.5199908 0.7406257 0.8189163
log_longevity 0.3211015 0.7789730 0.2685122 0.6788985
log_clutch 0.7772686 0.0127173 -0.4717750 0.2227314
log_breading_age 0.2219011 0.8820929 0.0033205 0.7780989
log_brood 0.7178213 -0.4592167 -0.2670217 0.2821787
Log_Hatchling_Mass 0.0050000 0.4320945 0.8990557 0.9950000
LS0tCnRpdGxlOiAiRmFjdG9yIEFuYWx5c2lzIHdpdGggZmVtYWxlIGJvZHkgbWFzcyIKYXV0aG9yOiAiTWFyaWEgTm92b3NvbG92IgpkYXRlOiAiYHIgU3lzLkRhdGUoKWAiCm91dHB1dDogCiAgaHRtbF9kb2N1bWVudDoKICAgIHRvYzogdHJ1ZQogICAgdG9jX2Zsb2F0OiB0cnVlCiAgICB0b2NfZGVwdGg6IDQKICAgIHRoZW1lOiB1bml0ZWQKICAgIGhpZ2hsaWdodDogdGFuZ28KICAgIGNvZGVfZm9sZGluZzogc2hvdwogICAgY29kZV9kb3dubG9hZDogdHJ1ZQogICAgZm9udDogRmlyYUNvZGUKLS0tCgpMb2FkIHRoZSBsaWJyYXJpZXMKYGBge3J9CmtuaXRyOjpvcHRzX2tuaXQkc2V0KHJvb3QuZGlyID0gIHJwcm9qcm9vdDo6ZmluZF9yc3R1ZGlvX3Jvb3RfZmlsZSgpKQprbml0cjo6b3B0c19jaHVuayRzZXQoZWNobyA9IFRSVUUpCnBhY21hbjo6cF9sb2FkKHRpZHl2ZXJzZSx2ZWdhbixHUEFyb3RhdGlvbixwc3ljaCxNQVNTLGZhY3RvZXh0cmEsY2x1c3RlcixmcGMsRmFjdG9NaW5lUixjb3dwbG90LGJyb29tLG1vZGVscixwc3kpCgpgYGAKCiMjIyBDcmVhdGUgdGhlIGN1cmF0ZWQgZGF0YXNldAoKTG9nIHRyYW5zZm9ybSB3aGF0IGlzIG5lZWRlZCBhbmQgc2VsZWN0IHRoZSBuZWVkZWQgY29sdW1ucwpgYGB7cn0Kc291cmNlKCJzY3JpcHRzL3RoZW1lX2dlb21ldHJ5LlIiKQp0ZXRyYXBvZF9kYXRhPC0gcmVhZHI6OnJlYWRfY3N2KCJkYXRhL1RldHJhcG9kIGxpZmUgaGlzdG9yeSBkYXRhYmFzZSBmb3IgbWFyaWEgMzEuMS4yMC5jc3YiKSAlPiUgCiAgZHJvcF9uYSgpICU+JSAKICBtdXRhdGUobG9nX2xvbmdldml0eSA9IGxvZzEwKE1heF9Mb25nZXZpdHkpLAogICAgICAgICBsb2dfY2x1dGNoID0gbG9nMTAoQ2x1dGNoX0xpdHRlcl9zaXplKSwKICAgICAgICAgbG9nX2JyZWFkaW5nX2FnZSA9IGxvZzEwKE1lYW5fYWdlX2F0X2JyZWVkaW5nKSwKICAgICAgICAgbG9nX2Jyb29kID0gbG9nMTAoTWF4aW11bV9Ccm9vZHNfcGVyX3llYXIpKQoKdGV0cmFwb2RfZGF0YTwtIHRldHJhcG9kX2RhdGEgJT4lIAogIGRwbHlyOjpzZWxlY3QoQ2xhc3MsIExvZ19GZW1hbGVfTWFzcywgbG9nX2xvbmdldml0eSxsb2dfY2x1dGNoLGxvZ19icmVhZGluZ19hZ2UsbG9nX2Jyb29kLExvZ19IYXRjaGxpbmdfTWFzcykKCmhlYWQodGV0cmFwb2RfZGF0YSkKCmBgYAoKUnVubmluZyB0aGUgRkEgbW9kZWwgYW5kIGV4dHJhY3RpbmcgdGhlIGZhY3RvcnMgZm9yIDEsMiwgYW5kIDMgZmFjdG9ycy4gQW5kIHJ1bm5pbmcgdGhlIE1GQSBtb2RlbApTdG9yaW5nIGV2ZXJ5dGhpbmcgaW4gYSBuZXN0ZWQgZGF0YXNldApgYGB7cn0KI2NyZWF0ZSBhIG5lc3RlZCBkYXRhc2V0IHdpdGggYWxsIHRoZSB0ZXRyYXBvZHMKYWxsX3RldHJhX25lc3Q8LSB0ZXRyYXBvZF9kYXRhICU+JSAKICBkcGx5cjo6c2VsZWN0KC1DbGFzcykgJT4lIAogIG5lc3QoKSAlPiUKICBhZGRfY29sdW1uKENsYXNzID0gIlRldHJhcG9kcyIsLmJlZm9yZSA9IDEpCgojY3JlYXRlIGEgbmVzdGVkIGRhdGFzZXQgYnkgY2xhc3MsIGFkZCB0aGUgd2hvbGUgdGV0cmFwb2RzIGFuZCBtYXAgdGhlIG1vZGVscyBpbnRvIHRoZW0KdGV0cmFwb2RfbmVzdGVkPC0gdGV0cmFwb2RfZGF0YSAlPiUKICBuZXN0KC1DbGFzcykgJT4lCiAgYmluZF9yb3dzKGFsbF90ZXRyYV9uZXN0KSAlPiUgCiAgbXV0YXRlKG1vZGVsLmZhMSA9IG1hcChkYXRhLCBmdW5jdGlvbihkZikgZmFjdGFuYWwoZGYsMSxyb3RhdGlvbj0idmFyaW1heCIsc2NvcmVzID0gInJlZ3Jlc3Npb24iKSkpICU+JSAKICBtdXRhdGUobW9kZWwuZmEyID0gbWFwKGRhdGEsIGZ1bmN0aW9uKGRmKSBmYWN0YW5hbChkZiwyLHJvdGF0aW9uPSJ2YXJpbWF4IixzY29yZXMgPSAicmVncmVzc2lvbiIpKSkgJT4lIAogIG11dGF0ZShtb2RlbC5mYTMgPSBtYXAoZGF0YSwgZnVuY3Rpb24oZGYpIGZhY3RhbmFsKGRmLDMscm90YXRpb249InZhcmltYXgiLHNjb3JlcyA9ICJyZWdyZXNzaW9uIikpKSAlPiUKICBtdXRhdGUobW9kZWwubWZhID0gbWFwKGRhdGEsIGZ1bmN0aW9uIChkZikgTUZBKGRmLGdyb3VwID0gYygxLDEsMSwxLDEsMSksIHR5cGU9YyhyZXAoInMiLDEpLHJlcCgicyIsMSkscmVwKCJzIiwxKSxyZXAoInMiLDEpLHJlcCgicyIsMSkscmVwKCJzIiwxKSksbmFtZS5ncm91cCA9IGMoIkJvZHkgU2l6ZSIsIkxvbmdldml0eSIsIkNsdXRjaCBzaXplIiwiQWdlIGF0IGJyZWVkaW5nIiwiQnJvb2QgZnJlcSIsIkhhdGNobGluZyBtYXNzIiksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBuY3AgPSA1LGdyYXBoID0gRikpKSAlPiUgCiAgZ3JvdXBfYnkoQ2xhc3MpICU+JSAKICBtdXRhdGUobW9kZWwuZmExLnIgPSBtYXAobW9kZWwuZmExLCBmdW5jdGlvbihtb2RlbCkgYnJvb206OnRpZHkobW9kZWwpKSwgCiAgICAgICAgIG1vZGVsLmZhMi5yID0gbWFwKG1vZGVsLmZhMiwgZnVuY3Rpb24obW9kZWwpIGJyb29tOjp0aWR5KG1vZGVsKSksCiAgICAgICAgIG1vZGVsLmZhMy5yID0gbWFwKG1vZGVsLmZhMywgZnVuY3Rpb24obW9kZWwpIGJyb29tOjp0aWR5KG1vZGVsKSkpICU+JSAKICBtdXRhdGUobW9kZWwuZmExLnIgPSBtYXAobW9kZWwuZmExLnIsIGZ1bmN0aW9uIChkZikgbXV0YXRlKGRmLCBjb20udmFyID0gMSAtIHVuaXF1ZW5lc3MpKSwKICAgICAgICAgbW9kZWwuZmEyLnIgPSBtYXAobW9kZWwuZmEyLnIsIGZ1bmN0aW9uIChkZikgbXV0YXRlKGRmLCBjb20udmFyID0gMSAtIHVuaXF1ZW5lc3MpKSwKICAgICAgICAgbW9kZWwuZmEzLnIgPSBtYXAobW9kZWwuZmEzLnIsIGZ1bmN0aW9uIChkZikgbXV0YXRlKGRmLCBjb20udmFyID0gMSAtIHVuaXF1ZW5lc3MpKSkgJT4lIAogIG11dGF0ZShtZmEuY29vcmQgPSBtYXAobW9kZWwubWZhLGZ1bmN0aW9uKG1mYSkgbWZhJHF1YW50aS52YXIkY29vcmRbLDE6M10pKQoKIyBjaGVjayB0aGUgZGF0YQp0ZXRyYXBvZF9uZXN0ZWQKYGBgCgojIyBNYW1tYWxzIHsudGFic2V0fQoKIyMjIE11bHRpcGxlIEZhY3RvciBBbmFseXNpcyAoTUZBKQoKQ3JlYXRlIHRoZSBzdWJzZXQgZGF0YXNldAoKYGBge3J9Cm1hbW1hbHM8LSB0ZXRyYXBvZF9uZXN0ZWQgJT4lIAogIGZpbHRlcihDbGFzcyA9PSAiTWFtbWFsaWEiKQpgYGAKCkNoZWNrIHRoZSBwZXJjZW50YWdlIGZvciBlYWNoIGF4aXMgaW4gdGhlIE1GQSAKYGBge3J9Cm1hcChtYW1tYWxzJG1vZGVsLm1mYSx+ZnZpel9zY3JlZXBsb3QoLikpCmBgYAoKV2Ugc2VlIHRoYXQgdGhlIGZpcnN0IGRpbWVudGlvbiBleHBsYWluIG1vc3Qgb2YgdGhlIHZhcmlhdGlvbiBzbyB3ZSB3aWxsIHBsb3QgdGhlIGZpcnN0IGFuZCB0aGUgc2Vjb25kLgpOb3cgd2Ugd2lsbCBleHBsb3JlIHRoZSByZXN1bHRzLiAKCkZpcnN0IGxldHMgc2VlIGhvdyB0aGV5IGRpc3BlcnNlIGluIHNwYWNlCmBgYHtyfQptYXAobWFtbWFscyRtb2RlbC5tZmEsfmZ2aXpfbWZhX3ZhciguLCAicXVhbnRpLnZhciIsIHBhbGV0dGUgPSAiamNvIiwgCiAgICAgICAgICAgICBjb2wudmFyLnN1cCA9ICJ2aW9sZXQiLCByZXBlbCA9IFRSVUUsCiAgICAgICAgICAgICBnZW9tID0gYygicG9pbnQiLCAidGV4dCIpLCBsZWdlbmQgPSAibm9uZSIsdGl0bGUgPSAiTWFtbWFscyIpKQpgYGAKCkV4cGxvcmUgdGhlIGNvbnRyaWJ1dGlvbiBvZiBlYWNoIHRyYWl0IHRvIHRoZSBheGVzCmBgYHtyfQojdGhlIGNvbnRyaWJ1dGlvbiBvZiB0aGUgZmlyc3QgYXhpcwpwbTE8LSBtYXAobWFtbWFscyRtb2RlbC5tZmEsfmZ2aXpfY29udHJpYiguLCAiZ3JvdXAiLCBheGVzID0gMSx0aXRsZT0gIkNvbnRyaWJ1dGlvbiBvZiB0cmFpdHMgdG8gZmlyc3QgYXhpcy1tYW1tYWxzIikpCnBtMjwtIG1hcChtYW1tYWxzJG1vZGVsLm1mYSx+ZnZpel9jb250cmliKC4sICJncm91cCIsIGF4ZXMgPSAyLHRpdGxlPSAiQ29udHJpYnV0aW9uIG9mIHRyYWl0cyB0byBzZWNvbmQgYXhpcy1tYW1tYWxzIikpCmdtMTwtIHBsb3RfZ3JpZChwbTFbWzFdXSxwbTJbWzFdXSxsYWJlbHMgPSBjKCJBIiwiQiIpKQpnbTEKCmBgYAoKUGxvdCBlYWNoIHBvaW50IGFuZCBjb2xvciBpdCBiYXNlZCBvbiBpdHMgcXVhbGl0eSBvZiByZXByZXNlbnRhdGlvbiAKYGBge3J9Cm1hcChtYW1tYWxzJG1vZGVsLm1mYSx+ZnZpel9tZmFfaW5kKC4sIGNvbC5pbmQgPSAiY29zMiIsCiAgICAgICAgICAgICBncmFkaWVudC5jb2xzID0gYygiIzAwQUZCQiIsICIjRTdCODAwIiwgIiNGQzRFMDciKSwKICAgICAgICAgICAgIHJlcGVsID0gVFJVRSxsYWJlbCA9ICJub25lIikpCmBgYAoKCiMjIyBGYWN0b3IgQW5hbHlzaXMgd2l0aCBmYWN0YW5hbCBmdW5jdGlvbgoKIyMjIyBFeHBsb3JhdG9yeSBwb3dlcgoKV2UgY2FuIHNlZSB0aGF0IGluIGFsbCB0aGUgZmFjdG9ycyBpdCdzIHF1aXRlIHN0cm9uZyBleHBsb3JhdG9yeSBwb3dlci4KV2UgY2FuIHVzZSB0aGUgcGFyYWxsZWwgYW5hbHlzaXMgdG8gc2VlIGhvdyBtYW55IGZhY3RvcnMgd2Ugc2hvdWxkIHVzZS4gWW91IHNlZSB0aGF0IGJ5IGxvb2tpbmcgYXQgd2hlcmUgdGhlIGJsdWUgbGluZSAodGhlIGFjdHVhbCBkYXRhKSBicmVha3MgYW5kIHdoZXJlIHRoZSBkaWZmZXJlbmNlIGJldHdlZW4gdGhlIGJsdWUgbGluZSBhbmQgdGhlIHJlZCBsaW5lIChzaW11bGF0ZWQgZGF0YSkgaXMgdGhlIHNtYWxsZXN0LiBCYXNlZCBvbiB0aGlzIHRocmVlIG1pZ2h0IGJlIG1vcmUgc3V0aWJsZSBidXQgaXQgaGFzIDAgZGVncmVlcyBvZiBmcmVlZG9tIHNvIHdlIHdpbGwgdGFrZSAqKlR3byBGYWN0b3JzKiouIAoKYGBge3J9CnBhcmFsbGVsIDwtIGZhLnBhcmFsbGVsKG1hbW1hbHMkZGF0YVtbMV1dLCBmbSA9ICdtbCcsIGZhID0gJ2ZhJykKYGBgCgoKKipUaGUgcmVzdWx0cyBmb3IgVGhyZWUgZmFjdG9ycyoqCgpUaGUgY29tbW9uIHZhcmlhbmNlIChjb2x1bW4gY29tLnZhcikgc2hvd3MgaG93IG11Y2ggb2YgdGhlIHZhcmlhbmNlIGlzIHNoYXJlZCBiZXR3ZWVuIGEgc3BlY2lmaWMgdmFyaWFibGUgYW5kIHRoZSByZXN0IG9mIHRoZSB2YXJpYWJsZXMuIFRoZSBsYXJnZXIgdGhlIG51bWJlciB0aGUgbW9yZSBpbmZvcm1hdGl2ZSB0aGUgdmFyaWFibGUuCgpgYGB7cn0Ka25pdHI6OmthYmxlKHByaW50KG1hbW1hbHMkbW9kZWwuZmEyLnIpKQpgYGAKCiMjIyMgRmFjdG9yIGFuYWx5c2lzIHBsb3QKCmBgYHtyfQpnZ3Bsb3QobWFtbWFscyRtb2RlbC5mYTIucltbMV1dLGFlcyhmbDEsZmwyKSkrCiAgdGhlbWVfZ2VvbWV0cnkobWFtbWFscyRtb2RlbC5mYTIucltbMV1dJGZsMSxtYW1tYWxzJG1vZGVsLmZhMi5yW1sxXV0kZmwyKSsKICBnZW9tX3BvaW50KCkrCiAgZ2VvbV90ZXh0KGFlcyhsYWJlbD12YXJpYWJsZSksaGp1c3Q9MC41LCB2anVzdD0tMSkKYGBgCgojIyBCaXJkcyB7LnRhYnNldH0KCiMjIyBNdWx0aXBsZSBGYWN0b3IgQW5hbHlzaXMgKE1GQSkKCkNyZWF0ZSB0aGUgc3Vic2V0IGRhdGFzZXQKCmBgYHtyfQpiaXJkczwtIHRldHJhcG9kX25lc3RlZCAlPiUgCiAgZmlsdGVyKENsYXNzID09ICJBdmVzIikKYGBgCgpDaGVjayB0aGUgcGVyY2VudGFnZSBmb3IgZWFjaCBheGlzIGluIHRoZSBNRkEgCmBgYHtyfQptYXAoYmlyZHMkbW9kZWwubWZhLH5mdml6X3NjcmVlcGxvdCguKSkKYGBgCgpXZSBzZWUgdGhhdCB0aGUgZmlyc3QgZGltZW50aW9uIGV4cGxhaW4gbW9zdCBvZiB0aGUgdmFyaWF0aW9uIHNvIHdlIHdpbGwgcGxvdCB0aGUgZmlyc3QgYW5kIHRoZSBzZWNvbmQuCk5vdyB3ZSB3aWxsIGV4cGxvcmUgdGhlIHJlc3VsdHMuIAoKRmlyc3QgbGV0cyBzZWUgaG93IHRoZXkgZGlzcGVyc2UgaW4gc3BhY2UKYGBge3J9Cm1hcChiaXJkcyRtb2RlbC5tZmEsfmZ2aXpfbWZhX3ZhciguLCAicXVhbnRpLnZhciIsIHBhbGV0dGUgPSAiamNvIiwgCiAgICAgICAgICAgICBjb2wudmFyLnN1cCA9ICJ2aW9sZXQiLCByZXBlbCA9IFRSVUUsCiAgICAgICAgICAgICBnZW9tID0gYygicG9pbnQiLCAidGV4dCIpLCBsZWdlbmQgPSAibm9uZSIsdGl0bGUgPSAiQmlyZHMiKSkKYGBgCgpFeHBsb3JlIHRoZSBjb250cmlidXRpb24gb2YgZWFjaCB0cmFpdCB0byB0aGUgYXhlcwpgYGB7cn0KI3RoZSBjb250cmlidXRpb24gb2YgdGhlIGZpcnN0IGF4aXMKcG0xPC0gbWFwKGJpcmRzJG1vZGVsLm1mYSx+ZnZpel9jb250cmliKC4sICJncm91cCIsIGF4ZXMgPSAxLHRpdGxlPSAiQ29udHJpYnV0aW9uIG9mIHRyYWl0cyB0byBmaXJzdCBheGlzLW1hbW1hbHMiKSkKcG0yPC0gbWFwKGJpcmRzJG1vZGVsLm1mYSx+ZnZpel9jb250cmliKC4sICJncm91cCIsIGF4ZXMgPSAyLHRpdGxlPSAiQ29udHJpYnV0aW9uIG9mIHRyYWl0cyB0byBzZWNvbmQgYXhpcy1tYW1tYWxzIikpCmdtMTwtIHBsb3RfZ3JpZChwbTFbWzFdXSxwbTJbWzFdXSxsYWJlbHMgPSBjKCJBIiwiQiIpKQpnbTEKCmBgYAoKUGxvdCBlYWNoIHBvaW50IGFuZCBjb2xvciBpdCBiYXNlZCBvbiBpdHMgcXVhbGl0eSBvZiByZXByZXNlbnRhdGlvbiAKYGBge3J9Cm1hcChiaXJkcyRtb2RlbC5tZmEsfmZ2aXpfbWZhX2luZCguLCBjb2wuaW5kID0gImNvczIiLAogICAgICAgICAgICAgZ3JhZGllbnQuY29scyA9IGMoIiMwMEFGQkIiLCAiI0U3QjgwMCIsICIjRkM0RTA3IiksCiAgICAgICAgICAgICByZXBlbCA9IFRSVUUsbGFiZWwgPSAibm9uZSIpKQpgYGAKCgojIyMgRmFjdG9yIEFuYWx5c2lzIHdpdGggZmFjdGFuYWwgZnVuY3Rpb24KCiMjIyMgRXhwbG9yYXRvcnkgcG93ZXIKCldlIGNhbiBzZWUgdGhhdCBpbiBhbGwgdGhlIGZhY3RvcnMgaXQncyBxdWl0ZSBzdHJvbmcgZXhwbG9yYXRvcnkgcG93ZXIuCldlIGNhbiB1c2UgdGhlIHBhcmFsbGVsIGFuYWx5c2lzIHRvIHNlZSBob3cgbWFueSBmYWN0b3JzIHdlIHNob3VsZCB1c2UuIEluIG91ciBjYXNlIGl0J3MgKipUd28gRmFjdG9ycyoqCgpgYGB7cn0KcGFyYWxsZWwgPC0gZmEucGFyYWxsZWwoYmlyZHMkZGF0YVtbMV1dLCBmbSA9ICdtbCcsIGZhID0gJ2ZhJykKYGBgCgoKKipUaGUgcmVzdWx0cyBmb3IgVHdvIGZhY3RvcnMqKgoKVGhlIGNvbW1vbiB2YXJpYW5jZSAoY29sdW1uIGNvbS52YXIpIHNob3dzIGhvdyBtdWNoIG9mIHRoZSB2YXJpYW5jZSBpcyBzaGFyZWQgYmV0d2VlbiBhIHNwZWNpZmljIHZhcmlhYmxlIGFuZCB0aGUgcmVzdCBvZiB0aGUgdmFyaWFibGVzLiBUaGUgbGFyZ2VyIHRoZSBudW1iZXIgdGhlIG1vcmUgaW5mb3JtYXRpdmUgdGhlIHZhcmlhYmxlLgoKYGBge3J9CmtuaXRyOjprYWJsZShwcmludChiaXJkcyRtb2RlbC5mYTIucikpCmBgYAoKIyMjIyBGYWN0b3IgYW5hbHlzaXMgcGxvdAoKYGBge3J9CmdncGxvdChiaXJkcyRtb2RlbC5mYTIucltbMV1dLGFlcyhmbDEsZmwyKSkrCiAgdGhlbWVfZ2VvbWV0cnkoYmlyZHMkbW9kZWwuZmEyLnJbWzFdXSRmbDEsYmlyZHMkbW9kZWwuZmEyLnJbWzFdXSRmbDIpKwogIGdlb21fcG9pbnQoKSsKICBnZW9tX3RleHQoYWVzKGxhYmVsPXZhcmlhYmxlKSxoanVzdD0wLjUsIHZqdXN0PS0xKQpgYGAKCgojIyBSZXB0aWxlcyB7LnRhYnNldH0KCiMjIyBNdWx0aXBsZSBGYWN0b3IgQW5hbHlzaXMgKE1GQSkKCkNyZWF0ZSB0aGUgc3Vic2V0IGRhdGFzZXQKCmBgYHtyfQpyZXB0aWxlczwtIHRldHJhcG9kX25lc3RlZCAlPiUgCiAgZmlsdGVyKENsYXNzID09ICJSZXB0aWxpYSIpCmBgYAoKQ2hlY2sgdGhlIHBlcmNlbnRhZ2UgZm9yIGVhY2ggYXhpcyBpbiB0aGUgTUZBIApgYGB7cn0KbWFwKHJlcHRpbGVzJG1vZGVsLm1mYSx+ZnZpel9zY3JlZXBsb3QoLikpCmBgYAoKV2Ugc2VlIHRoYXQgdGhlIGZpcnN0IGRpbWVudGlvbiBleHBsYWluIG1vc3Qgb2YgdGhlIHZhcmlhdGlvbiBzbyB3ZSB3aWxsIHBsb3QgdGhlIGZpcnN0IGFuZCB0aGUgc2Vjb25kLgpOb3cgd2Ugd2lsbCBleHBsb3JlIHRoZSByZXN1bHRzLiAKCkZpcnN0IGxldHMgc2VlIGhvdyB0aGV5IGRpc3BlcnNlIGluIHNwYWNlCmBgYHtyfQptYXAocmVwdGlsZXMkbW9kZWwubWZhLH5mdml6X21mYV92YXIoLiwgInF1YW50aS52YXIiLCBwYWxldHRlID0gImpjbyIsIAogICAgICAgICAgICAgY29sLnZhci5zdXAgPSAidmlvbGV0IiwgcmVwZWwgPSBUUlVFLAogICAgICAgICAgICAgZ2VvbSA9IGMoInBvaW50IiwgInRleHQiKSwgbGVnZW5kID0gIm5vbmUiLHRpdGxlID0gIlJlcHRpbGVzIikpCmBgYAoKRXhwbG9yZSB0aGUgY29udHJpYnV0aW9uIG9mIGVhY2ggdHJhaXQgdG8gdGhlIGF4ZXMKYGBge3J9CiN0aGUgY29udHJpYnV0aW9uIG9mIHRoZSBmaXJzdCBheGlzCnBtMTwtIG1hcChyZXB0aWxlcyRtb2RlbC5tZmEsfmZ2aXpfY29udHJpYiguLCAiZ3JvdXAiLCBheGVzID0gMSx0aXRsZT0gIkNvbnRyaWJ1dGlvbiBvZiB0cmFpdHMgdG8gZmlyc3QgYXhpcy1tYW1tYWxzIikpCnBtMjwtIG1hcChyZXB0aWxlcyRtb2RlbC5tZmEsfmZ2aXpfY29udHJpYiguLCAiZ3JvdXAiLCBheGVzID0gMix0aXRsZT0gIkNvbnRyaWJ1dGlvbiBvZiB0cmFpdHMgdG8gc2Vjb25kIGF4aXMtbWFtbWFscyIpKQpnbTE8LSBwbG90X2dyaWQocG0xW1sxXV0scG0yW1sxXV0sbGFiZWxzID0gYygiQSIsIkIiKSkKZ20xCgpgYGAKClBsb3QgZWFjaCBwb2ludCBhbmQgY29sb3IgaXQgYmFzZWQgb24gaXRzIHF1YWxpdHkgb2YgcmVwcmVzZW50YXRpb24gCmBgYHtyfQptYXAocmVwdGlsZXMkbW9kZWwubWZhLH5mdml6X21mYV9pbmQoLiwgY29sLmluZCA9ICJjb3MyIiwKICAgICAgICAgICAgIGdyYWRpZW50LmNvbHMgPSBjKCIjMDBBRkJCIiwgIiNFN0I4MDAiLCAiI0ZDNEUwNyIpLAogICAgICAgICAgICAgcmVwZWwgPSBUUlVFLGxhYmVsID0gIm5vbmUiKSkKYGBgCgoKIyMjIEZhY3RvciBBbmFseXNpcyB3aXRoIGZhY3RhbmFsIGZ1bmN0aW9uCgojIyMjIEV4cGxvcmF0b3J5IHBvd2VyCgpXZSBjYW4gc2VlIHRoYXQgaW4gYWxsIHRoZSBmYWN0b3JzIGl0J3MgcXVpdGUgc3Ryb25nIGV4cGxvcmF0b3J5IHBvd2VyLgpXZSBjYW4gdXNlIHRoZSBwYXJhbGxlbCBhbmFseXNpcyB0byBzZWUgaG93IG1hbnkgZmFjdG9ycyB3ZSBzaG91bGQgdXNlLiBJbiBvdXIgY2FzZSBpdCdzICoqVHdvIEZhY3RvcnMqKgoKYGBge3J9CnBhcmFsbGVsIDwtIGZhLnBhcmFsbGVsKHJlcHRpbGVzJGRhdGFbWzFdXSwgZm0gPSAnbWwnLCBmYSA9ICdmYScpCmBgYAoKCioqVGhlIHJlc3VsdHMgZm9yIFR3byBmYWN0b3JzKioKClRoZSBjb21tb24gdmFyaWFuY2UgKGNvbHVtbiBjb20udmFyKSBzaG93cyBob3cgbXVjaCBvZiB0aGUgdmFyaWFuY2UgaXMgc2hhcmVkIGJldHdlZW4gYSBzcGVjaWZpYyB2YXJpYWJsZSBhbmQgdGhlIHJlc3Qgb2YgdGhlIHZhcmlhYmxlcy4gVGhlIGxhcmdlciB0aGUgbnVtYmVyIHRoZSBtb3JlIGluZm9ybWF0aXZlIHRoZSB2YXJpYWJsZS4KCmBgYHtyfQprbml0cjo6a2FibGUocHJpbnQocmVwdGlsZXMkbW9kZWwuZmEyLnIpKQpgYGAKCiMjIyMgRmFjdG9yIGFuYWx5c2lzIHBsb3QKCmBgYHtyfQpnZ3Bsb3QocmVwdGlsZXMkbW9kZWwuZmEyLnJbWzFdXSxhZXMoZmwxLGZsMikpKwogIHRoZW1lX2dlb21ldHJ5KHJlcHRpbGVzJG1vZGVsLmZhMi5yW1sxXV0kZmwxLHJlcHRpbGVzJG1vZGVsLmZhMi5yW1sxXV0kZmwyKSsKICBnZW9tX3BvaW50KCkrCiAgZ2VvbV90ZXh0KGFlcyhsYWJlbD12YXJpYWJsZSksaGp1c3Q9MC41LCB2anVzdD0tMSkKYGBgCgojIyBBbXBoaWJpYW5zIHsudGFic2V0fQoKIyMjIE11bHRpcGxlIEZhY3RvciBBbmFseXNpcyAoTUZBKQoKQ3JlYXRlIHRoZSBzdWJzZXQgZGF0YXNldAoKYGBge3J9CmFtcGg8LSB0ZXRyYXBvZF9uZXN0ZWQgJT4lIAogIGZpbHRlcihDbGFzcyA9PSAiQW1waGliaWEiKQpgYGAKCkNoZWNrIHRoZSBwZXJjZW50YWdlIGZvciBlYWNoIGF4aXMgaW4gdGhlIE1GQSAKYGBge3J9Cm1hcChhbXBoJG1vZGVsLm1mYSx+ZnZpel9zY3JlZXBsb3QoLikpCmBgYAoKV2Ugc2VlIHRoYXQgdGhlIGZpcnN0IGRpbWVudGlvbiBleHBsYWluIG1vc3Qgb2YgdGhlIHZhcmlhdGlvbiBzbyB3ZSB3aWxsIHBsb3QgdGhlIGZpcnN0IGFuZCB0aGUgc2Vjb25kLgpOb3cgd2Ugd2lsbCBleHBsb3JlIHRoZSByZXN1bHRzLiAKCkZpcnN0IGxldHMgc2VlIGhvdyB0aGV5IGRpc3BlcnNlIGluIHNwYWNlCmBgYHtyfQptYXAoYW1waCRtb2RlbC5tZmEsfmZ2aXpfbWZhX3ZhciguLCAicXVhbnRpLnZhciIsIHBhbGV0dGUgPSAiamNvIiwgCiAgICAgICAgICAgICBjb2wudmFyLnN1cCA9ICJ2aW9sZXQiLCByZXBlbCA9IFRSVUUsCiAgICAgICAgICAgICBnZW9tID0gYygicG9pbnQiLCAidGV4dCIpLCBsZWdlbmQgPSAibm9uZSIsdGl0bGUgPSAiQW1waGliaWFucyIpKQpgYGAKCkV4cGxvcmUgdGhlIGNvbnRyaWJ1dGlvbiBvZiBlYWNoIHRyYWl0IHRvIHRoZSBheGVzCmBgYHtyfQojdGhlIGNvbnRyaWJ1dGlvbiBvZiB0aGUgZmlyc3QgYXhpcwpwbTE8LSBtYXAoYW1waCRtb2RlbC5tZmEsfmZ2aXpfY29udHJpYiguLCAiZ3JvdXAiLCBheGVzID0gMSx0aXRsZT0gIkNvbnRyaWJ1dGlvbiBvZiB0cmFpdHMgdG8gZmlyc3QgYXhpcy1tYW1tYWxzIikpCnBtMjwtIG1hcChhbXBoJG1vZGVsLm1mYSx+ZnZpel9jb250cmliKC4sICJncm91cCIsIGF4ZXMgPSAyLHRpdGxlPSAiQ29udHJpYnV0aW9uIG9mIHRyYWl0cyB0byBzZWNvbmQgYXhpcy1tYW1tYWxzIikpCmdtMTwtIHBsb3RfZ3JpZChwbTFbWzFdXSxwbTJbWzFdXSxsYWJlbHMgPSBjKCJBIiwiQiIpKQpnbTEKCmBgYAoKUGxvdCBlYWNoIHBvaW50IGFuZCBjb2xvciBpdCBiYXNlZCBvbiBpdHMgcXVhbGl0eSBvZiByZXByZXNlbnRhdGlvbiAKYGBge3J9Cm1hcChhbXBoJG1vZGVsLm1mYSx+ZnZpel9tZmFfaW5kKC4sIGNvbC5pbmQgPSAiY29zMiIsCiAgICAgICAgICAgICBncmFkaWVudC5jb2xzID0gYygiIzAwQUZCQiIsICIjRTdCODAwIiwgIiNGQzRFMDciKSwKICAgICAgICAgICAgIHJlcGVsID0gVFJVRSxsYWJlbCA9ICJub25lIikpCmBgYAoKCiMjIyBGYWN0b3IgQW5hbHlzaXMgd2l0aCBmYWN0YW5hbCBmdW5jdGlvbgoKIyMjIyBFeHBsb3JhdG9yeSBwb3dlcgoKV2UgY2FuIHNlZSB0aGF0IGluIGFsbCB0aGUgZmFjdG9ycyBpdCdzIHF1aXRlIHN0cm9uZyBleHBsb3JhdG9yeSBwb3dlci4KV2UgY2FuIHVzZSB0aGUgcGFyYWxsZWwgYW5hbHlzaXMgdG8gc2VlIGhvdyBtYW55IGZhY3RvcnMgd2Ugc2hvdWxkIHVzZS4gSW4gb3VyIGNhc2UgaXQncyAqKlR3byBGYWN0b3JzKioKCmBgYHtyfQpwYXJhbGxlbCA8LSBmYS5wYXJhbGxlbChhbXBoJGRhdGFbWzFdXSwgZm0gPSAnbWwnLCBmYSA9ICdmYScpCmBgYAoKCioqVGhlIHJlc3VsdHMgZm9yIFR3byBmYWN0b3JzKioKClRoZSBjb21tb24gdmFyaWFuY2UgKGNvbHVtbiBjb20udmFyKSBzaG93cyBob3cgbXVjaCBvZiB0aGUgdmFyaWFuY2UgaXMgc2hhcmVkIGJldHdlZW4gYSBzcGVjaWZpYyB2YXJpYWJsZSBhbmQgdGhlIHJlc3Qgb2YgdGhlIHZhcmlhYmxlcy4gVGhlIGxhcmdlciB0aGUgbnVtYmVyIHRoZSBtb3JlIGluZm9ybWF0aXZlIHRoZSB2YXJpYWJsZS4KCkluIGhlcmUgeW91IHNlZSB0aGF0IHNvbWUgb2YgdGhlIHZhcmlhYmxlcyBkb24ndCBhZGQgbXVjaCB0byB0aGUgbW9kZWwgKGNvbS52YXIgaXMgbG93KQoKYGBge3J9CmtuaXRyOjprYWJsZShwcmludChhbXBoJG1vZGVsLmZhMi5yKSkKYGBgCgojIyMjIEZhY3RvciBhbmFseXNpcyBwbG90CgpgYGB7cn0KZ2dwbG90KGFtcGgkbW9kZWwuZmEyLnJbWzFdXSxhZXMoZmwxLGZsMikpKwogIHRoZW1lX2dlb21ldHJ5KGFtcGgkbW9kZWwuZmEyLnJbWzFdXSRmbDEsYW1waCRtb2RlbC5mYTIucltbMV1dJGZsMikrCiAgZ2VvbV9wb2ludCgpKwogIGdlb21fdGV4dChhZXMobGFiZWw9dmFyaWFibGUpLGhqdXN0PTAuNSwgdmp1c3Q9LTEpCmBgYAoKCiMjIEFsbCB0ZXRyYXBvZHMgey50YWJzZXR9CgojIyMgTXVsdGlwbGUgRmFjdG9yIEFuYWx5c2lzIChNRkEpCgpDcmVhdGUgdGhlIHN1YnNldCBkYXRhc2V0CgpgYGB7cn0KYWxsLnRldHJhcG9kczwtIHRldHJhcG9kX25lc3RlZCAlPiUgCiAgZmlsdGVyKENsYXNzID09ICJUZXRyYXBvZHMiKQpgYGAKCkNoZWNrIHRoZSBwZXJjZW50YWdlIGZvciBlYWNoIGF4aXMgaW4gdGhlIE1GQSAKYGBge3J9Cm1hcChhbGwudGV0cmFwb2RzJG1vZGVsLm1mYSx+ZnZpel9zY3JlZXBsb3QoLikpCmBgYAoKV2Ugc2VlIHRoYXQgdGhlIGZpcnN0IGRpbWVudGlvbiBleHBsYWluIG1vc3Qgb2YgdGhlIHZhcmlhdGlvbiBzbyB3ZSB3aWxsIHBsb3QgdGhlIGZpcnN0IGFuZCB0aGUgc2Vjb25kLgpOb3cgd2Ugd2lsbCBleHBsb3JlIHRoZSByZXN1bHRzLiAKCkZpcnN0IGxldHMgc2VlIGhvdyB0aGV5IGRpc3BlcnNlIGluIHNwYWNlCmBgYHtyfQptYXAoYWxsLnRldHJhcG9kcyRtb2RlbC5tZmEsfmZ2aXpfbWZhX3ZhciguLCAicXVhbnRpLnZhciIsIHBhbGV0dGUgPSAiamNvIiwgCiAgICAgICAgICAgICBjb2wudmFyLnN1cCA9ICJ2aW9sZXQiLCByZXBlbCA9IFRSVUUsCiAgICAgICAgICAgICBnZW9tID0gYygicG9pbnQiLCAidGV4dCIpLCBsZWdlbmQgPSAibm9uZSIsdGl0bGUgPSAiQWxsIHRldHJhcG9kcyIpKQpgYGAKCkV4cGxvcmUgdGhlIGNvbnRyaWJ1dGlvbiBvZiBlYWNoIHRyYWl0IHRvIHRoZSBheGVzCmBgYHtyfQojdGhlIGNvbnRyaWJ1dGlvbiBvZiB0aGUgZmlyc3QgYXhpcwpwbTE8LSBtYXAoYWxsLnRldHJhcG9kcyRtb2RlbC5tZmEsfmZ2aXpfY29udHJpYiguLCAiZ3JvdXAiLCBheGVzID0gMSx0aXRsZT0gIkNvbnRyaWJ1dGlvbiBvZiB0cmFpdHMgdG8gZmlyc3QgYXhpcy1tYW1tYWxzIikpCnBtMjwtIG1hcChhbGwudGV0cmFwb2RzJG1vZGVsLm1mYSx+ZnZpel9jb250cmliKC4sICJncm91cCIsIGF4ZXMgPSAyLHRpdGxlPSAiQ29udHJpYnV0aW9uIG9mIHRyYWl0cyB0byBzZWNvbmQgYXhpcy1tYW1tYWxzIikpCmdtMTwtIHBsb3RfZ3JpZChwbTFbWzFdXSxwbTJbWzFdXSxsYWJlbHMgPSBjKCJBIiwiQiIpKQpnbTEKCmBgYAoKUGxvdCBlYWNoIHBvaW50IGFuZCBjb2xvciBpdCBiYXNlZCBvbiBpdHMgcXVhbGl0eSBvZiByZXByZXNlbnRhdGlvbiAKYGBge3J9Cm1hcChhbGwudGV0cmFwb2RzJG1vZGVsLm1mYSx+ZnZpel9tZmFfaW5kKC4sIGNvbC5pbmQgPSAiY29zMiIsCiAgICAgICAgICAgICBncmFkaWVudC5jb2xzID0gYygiIzAwQUZCQiIsICIjRTdCODAwIiwgIiNGQzRFMDciKSwKICAgICAgICAgICAgIHJlcGVsID0gVFJVRSxsYWJlbCA9ICJub25lIikpCmBgYAoKCiMjIyBGYWN0b3IgQW5hbHlzaXMgd2l0aCBmYWN0YW5hbCBmdW5jdGlvbgoKIyMjIyBFeHBsb3JhdG9yeSBwb3dlcgoKV2UgY2FuIHNlZSB0aGF0IGluIGFsbCB0aGUgZmFjdG9ycyBpdCdzIHF1aXRlIHN0cm9uZyBleHBsb3JhdG9yeSBwb3dlci4KV2UgY2FuIHVzZSB0aGUgcGFyYWxsZWwgYW5hbHlzaXMgdG8gc2VlIGhvdyBtYW55IGZhY3RvcnMgd2Ugc2hvdWxkIHVzZS4gSW4gb3VyIGNhc2UgaXQncyAqKlR3byBGYWN0b3JzKioKCmBgYHtyfQpwYXJhbGxlbCA8LSBmYS5wYXJhbGxlbChhbGwudGV0cmFwb2RzJGRhdGFbWzFdXSwgZm0gPSAnbWwnLCBmYSA9ICdmYScpCmBgYAoKCioqVGhlIHJlc3VsdHMgZm9yIFR3byBmYWN0b3JzKioKClRoZSBjb21tb24gdmFyaWFuY2UgKGNvbHVtbiBjb20udmFyKSBzaG93cyBob3cgbXVjaCBvZiB0aGUgdmFyaWFuY2UgaXMgc2hhcmVkIGJldHdlZW4gYSBzcGVjaWZpYyB2YXJpYWJsZSBhbmQgdGhlIHJlc3Qgb2YgdGhlIHZhcmlhYmxlcy4gVGhlIGxhcmdlciB0aGUgbnVtYmVyIHRoZSBtb3JlIGluZm9ybWF0aXZlIHRoZSB2YXJpYWJsZS4KCmBgYHtyfQprbml0cjo6a2FibGUocHJpbnQoYWxsLnRldHJhcG9kcyRtb2RlbC5mYTIucikpCmBgYAoKIyMjIyBGYWN0b3IgYW5hbHlzaXMgcGxvdAoKYGBge3J9CmdncGxvdChhbGwudGV0cmFwb2RzJG1vZGVsLmZhMi5yW1sxXV0sYWVzKGZsMSxmbDIpKSsKICB0aGVtZV9nZW9tZXRyeShhbGwudGV0cmFwb2RzJG1vZGVsLmZhMi5yW1sxXV0kZmwxLGFsbC50ZXRyYXBvZHMkbW9kZWwuZmEyLnJbWzFdXSRmbDIpKwogIGdlb21fcG9pbnQoKSsKICBnZW9tX3RleHQoYWVzKGxhYmVsPXZhcmlhYmxlKSxoanVzdD0wLjUsIHZqdXN0PS0xKQpgYGAKCg==